classdef RankingSensitivity < MultiLabelMetric
    %COVERAGE Summary of this class goes here
    %   Detailed explanation goes here
    
    properties
    end
    
    methods
        function [ this ] = RankingSensitivity(  )
            if nargin == 0
                this.setName('ranking_sensitivity');
                return
            end
        end
    end
    
    methods
        function [ result ] = apply( this, Y, Y_hat, Y_out )
            assert(isequal(this.name, 'ranking_sensitivity'));
            result = RankingSensitivity.calc(Y, Y_out);
        end
    end
    
    methods ( Static = true )
        function [ result ] = calc( Y, Y_hat, Y_out )
            n_example = size(Y, 1);
            for i_example = 1:n_example
                Y_i = Y(i_example, :);
                Y_hat_i = Y_hat(i_example, :);
                Y_out_i = Y_out(i_example, :);
                result(i_example) = calc_individual_ranking_sensitivity( ...
                    Y_i, Y_hat_i, Y_out_i);
            end
            result = mean(result);
        end
    end
    
end

function [ result ] = calc_individual_ranking_sensitivity( Y, Y_hat, Y_out )

pos_id = Y_hat == 1;
n_pos = nnz(pos_id);
if n_pos == 0
    if all(Y ~= 1)
        result = 1;
    else
        result = 0;
    end
    return
end
min_pos_out = min(Y_out(pos_id));
tp_fp_id = Y_out >= min_pos_out;
result = nnz(Y(tp_fp_id) == 1)/nnz(tp_fp_id);

end
